home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / RCSC.ZIP / SRC / CC1.C < prev    next >
C/C++ Source or Header  |  1997-01-12  |  26KB  |  929 lines

  1. /*
  2. ** Concurrent Small C Language Features Added by Andy Yuen 1997
  3. ** Small-C Compiler -- Part 1 --  Top End.
  4. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  5. ** All rights reserved.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include "notice.h"
  10. #include "cc.h"
  11.  
  12. /*
  13. ** miscellaneous storage
  14. */
  15. int
  16.   nogo,     /* disable goto statements? */
  17.   noloc,    /* disable block locals? */
  18.   opindex,  /* index to matched operator */
  19.   opsize,   /* size of operator in characters */
  20.   swactive, /* inside a switch? */
  21.   swdefault,/* default label #, else 0 */
  22.  *swnext,   /* address of next entry */
  23.  *swend,    /* address of last entry */
  24.  *stage,    /* staging buffer address */
  25.  *wq,       /* while queue */
  26.   argcs,    /* static argc */
  27.  *argvs,    /* static argv */
  28.  *wqptr,    /* ptr to next entry */
  29.   litptr,   /* ptr to next entry */
  30.   macptr,   /* macro buffer index */
  31.   pptr,     /* ptr to parsing buffer */
  32.   ch,       /* current character of input line */
  33.   nch,      /* next character of input line */
  34.   declared, /* # of local bytes to declare, -1 when declared */
  35.   iflevel,  /* #if... nest level */
  36.   skiplevel,/* level at which #if... skipping started */
  37.   nxtlab,   /* next avail label # */
  38.   litlab,   /* label # assigned to literal pool */
  39.   csp,      /* compiler relative stk ptr */
  40.   argstk,   /* function arg sp */
  41.   argtop,   /* highest formal argument offset */
  42.   ncmp,     /* # open compound statements */
  43.   errflag,  /* true after 1st error in statement */
  44.   eof,      /* true on final input eof */
  45.   output,   /* fd for output file */
  46.   files,    /* true if file list specified on cmd line */
  47.   filearg,  /* cur file arg index */
  48.   input   = EOF, /* fd for input file */
  49.   input2  = EOF, /* fd for "#include" file */
  50.   usexpr  = YES, /* true if value of expression is used */
  51.   ccode   = YES, /* true while parsing C code */
  52.  *snext,    /* next addr in stage */
  53.  *stail,    /* last addr of data in stage */
  54.  *slast,    /* last addr in stage */
  55.   listfp,   /* file pointer to list device */
  56.   lastst,   /* last parsed statement type */
  57.   oldseg;   /* current segment (0, DATASEG, CODESEG) */
  58.  
  59. int 
  60.   moninit,  /* monitor keyword entercountered in module flag */
  61.   private,  /* static keyword beging processed flag */
  62.   entry;    /* entry keyword being processed flag */
  63.  
  64. char
  65.   optimize, /* optimize output of staging buffer? */
  66.   alarm,    /* audible alarm on errors? */
  67.   monitor,  /* monitor function headers? */
  68.   pause,    /* pause for operator on errors? */
  69.  *symtab,   /* symbol table */
  70.  *litq,     /* literal pool */
  71.  *macn,     /* macro name buffer */
  72.  *macq,     /* macro string buffer */
  73.  *pline,    /* parsing buffer */
  74.  *mline,    /* macro buffer */
  75.  *line,     /* ptr to pline or mline */
  76.  *lptr,     /* ptr to current character in "line" */
  77.  *glbptr,   /* global symbol table */
  78.  *locptr,   /* next local symbol table entry */
  79.   quote[2] = {'"'}, /* literal string for '"' */
  80.  *cptr,     /* work ptrs to any char buffer */
  81.  *cptr2,
  82.  *cptr3,
  83.   msname[NAMESIZE],   /* macro symbol name */
  84.   ssname[NAMESIZE];   /* static symbol name */
  85.  
  86. int op[16] = {   /* p-codes of signed binary operators */
  87.   OR12,                        /* level5 */
  88.   XOR12,                       /* level6 */
  89.   AND12,                       /* level7 */
  90.   EQ12,   NE12,                /* level8 */
  91.   LE12,   GE12,  LT12,  GT12,  /* level9 */
  92.   ASR12,  ASL12,               /* level10 */
  93.   ADD12,  SUB12,               /* level11 */
  94.   MUL12, DIV12, MOD12          /* level12 */
  95.   };
  96.  
  97. int op2[16] = {  /* p-codes of unsigned binary operators */
  98.   OR12,                        /* level5 */
  99.   XOR12,                       /* level6 */
  100.   AND12,                       /* level7 */
  101.   EQ12,   NE12,                /* level8 */
  102.   LE12u,  GE12u, LT12u, GT12u, /* level9 */
  103.   ASR12,  ASL12,               /* level10 */
  104.   ADD12,  SUB12,               /* level11 */
  105.   MUL12u, DIV12u, MOD12u       /* level12 */
  106.   };
  107.  
  108. /*
  109. ** execution begins here
  110. */
  111. main(argc, argv) int argc, *argv; {
  112.   fputs(VERSION, stderr);
  113.   fputs(CRIGHT1, stderr);
  114.   fputs(CRIGHT2, stderr);
  115.   argcs   = argc;
  116.   argvs   = argv;
  117.   swnext  = calloc(SWTABSZ, 1);
  118.   swend   = swnext+(SWTABSZ-SWSIZ);
  119.   stage   = calloc(STAGESIZE, 2*BPW);
  120.   wqptr   =
  121.   wq      = calloc(WQTABSZ, BPW);
  122.   litq    = calloc(LITABSZ, 1);
  123.   macn    = calloc(MACNSIZE, 1);
  124.   macq    = calloc(MACQSIZE, 1);
  125.   pline   = calloc(LINESIZE, 1);
  126.   mline   = calloc(LINESIZE, 1);
  127.   slast   = stage+(STAGESIZE*2*BPW);
  128.   symtab  = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
  129.   locptr  = STARTLOC;
  130.   glbptr  = STARTGLB;
  131.   
  132.   ask();          /* get user options */
  133.   openfile();     /* and initial input file */
  134.   preprocess();   /* fetch first line */
  135.   header();       /* intro code */
  136.   setcodes();     /* initialize code pointer array */ 
  137.   parse();        /* process ALL input */
  138.   trailer();      /* follow-up code */
  139.   fclose(output); /* explicitly close output */
  140.   }
  141.  
  142. /******************** high level parsing *******************/
  143.  
  144. /*
  145. ** process all input text
  146. **
  147. ** At this level, only static declarations,
  148. **      defines, includes and function
  149. **      definitions are legal...
  150. */
  151. parse() {
  152.   while (eof == 0) {
  153.     if     (amatch("extern", 6)) dodeclare(EXTERNAL);
  154.     else if(dodeclare(STATIC))   ;
  155.     else if( match("#asm"))      doasm();
  156.     else if( match("#include"))  doinclude();
  157.     else if( match("#define"))   dodefine();
  158.     else                         dofunction();
  159.     blanks();                 /* force eof if pending */
  160.     }
  161.   }
  162.  
  163. /*
  164. ** test for global declarations
  165. */
  166. dodeclare(class) int class; {
  167.   private = 0;
  168.   if (match("static")) {
  169.     blanks();
  170.     private = 1;
  171.     }
  172.   if     (amatch("char",     4))  declglb(CHR,  class);
  173.   else if(amatch("unsigned", 8)) {
  174.     if   (amatch("char",     4))  declglb(UCHR, class);
  175.     else {amatch("int",      3);  declglb(UINT, class);}
  176.     }
  177.   else if(amatch("int",      3)
  178.        || class == EXTERNAL)      declglb(INT,  class);
  179.   else return 0;
  180.   ns();
  181.   return 1;
  182.   }
  183.  
  184. /*
  185. ** declare a static variable
  186. */
  187. declglb(type, class)  int type, class; {
  188.   int id, dim;
  189.   while(1) {
  190.     if(endst()) return;  /* do line */
  191.     if(match("*"))       {id = POINTER;  dim = 0;}
  192.     else                 {id = VARIABLE; dim = 1;}
  193.     if(symname(ssname) == 0) illname();
  194.     if(findglb(ssname)) multidef(ssname);
  195.     if(id == VARIABLE) {
  196.       if     (match("("))  {id = FUNCTION; need(")");}
  197.       else if(match("["))  {id = ARRAY; dim = needsub();}
  198.       }
  199.     if     (class == EXTERNAL) external(ssname, type >> 2, id);
  200.     else if(   id != FUNCTION) initials(type >> 2, id, dim);
  201.     if(id == POINTER) 
  202.          addsym(ssname, id, type, BPW, 0, &glbptr, class);
  203.     else addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class);
  204.     if(match(",") == 0) return;
  205.     }
  206.   }
  207.  
  208. /*
  209. ** initialize global objects
  210. */
  211. initials(size, ident, dim) int size, ident, dim; {
  212.   int savedim;
  213.   litptr = 0;
  214.   if(dim == 0) dim = -1;         /* *... or ...[] */
  215.   savedim = dim;
  216.   if (private) {
  217.     /* do not make static variable public */
  218.     toseg(DATASEG);
  219.     sprintf(tmpbuf, "DECLARE(_%s)", ssname);
  220.     outline(tmpbuf);
  221.     }
  222.   else
  223.     public(ident);
  224.   if(match("=")) {
  225.     if(match("{")) {
  226.       while(dim) {
  227.         init(size, ident, &dim);
  228.         if(match(",") == 0) break;
  229.         }
  230.       need("}");
  231.       }
  232.     else init(size, ident, &dim);
  233.     }
  234.   if(savedim == -1 && dim == -1) {
  235.     if(ident == ARRAY) error("need array size");
  236.     stowlit(0, size = BPW);
  237.     }
  238.   dumplits(size);
  239.   dumpzero(size, dim);           /* only if dim > 0 */
  240.   }
  241.  
  242. /*
  243. ** evaluate one initializer
  244. */
  245. init(size, ident, dim) int size, ident, *dim; {
  246.   int value;
  247.   if(string(&value)) {
  248.     if(ident == VARIABLE || size != 1)
  249.       error("must assign to char pointer or char array");
  250.     *dim -= (litptr - value);
  251.     if(ident == POINTER) point();
  252.     }
  253.   else if(constexpr(&value)) {
  254.     if(ident == POINTER) error("cannot assign to pointer");
  255.     stowlit(value, size);
  256.     *dim -= 1;
  257.     }
  258.   }
  259.  
  260. /*
  261. ** get required array size
  262. */
  263. needsub()  {
  264.   int val;
  265.   if(match("]")) return 0; /* null size */
  266.   if(constexpr(&val) == 0) val = 1;
  267.   if(val < 0) {
  268.     error("negative size illegal");
  269.     val = -val;
  270.     }
  271.   need("]");               /* force single dimension */
  272.   return val;              /* and return size */
  273.   }
  274.  
  275. /*
  276. ** open an include file
  277. */
  278. doinclude() {
  279.   int i; char str[30];
  280.   blanks();       /* skip over to name */
  281.   if(*lptr == '"' || *lptr == '<') ++lptr;
  282.   i = 0;
  283.   while(lptr[i]
  284.      && lptr[i] != '"'
  285.      && lptr[i] != '>'
  286.      && lptr[i] != '\n') {
  287.     str[i] = lptr[i];
  288.     ++i;
  289.     }
  290.   str[i] = NULL;
  291.   if((input2 = fopen(str,"r")) == NULL) {
  292.     input2 = EOF;
  293.     error("open failure on include file");
  294.     }
  295.   kill();   /* make next read come from new file (if open) */
  296.   }
  297.  
  298. /*
  299. ** define a macro symbol
  300. */
  301. dodefine() {
  302.   int k;
  303.   if(symname(msname) == 0) {
  304.     illname();
  305.     kill();
  306.     return;
  307.     }
  308.   k = 0;
  309.   if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) {
  310.     if(cptr2 = cptr)
  311.       while(*cptr2++ = msname[k++]) ;
  312.     else {
  313.       error("macro name table full");
  314.       return;
  315.       }
  316.     }
  317.   putint(macptr, cptr+NAMESIZE, 2);
  318.   while(white()) gch();
  319.   while(putmac(gch()));
  320.   if(macptr >= MACMAX) {
  321.     error("macro string queue full");
  322.     abort(ERRCODE);
  323.     }
  324.   }
  325.  
  326. putmac(c)  char c; {
  327.   macq[macptr] = c;
  328.   if(macptr < MACMAX) ++macptr;
  329.   return c;
  330.   }
  331.  
  332. /* get task/interrupt function parameters */
  333. getparms(param, count)
  334. int *param; int count;
  335. {
  336.   int i, n;
  337.   n = 0;
  338.   for (i = 0; i < count; i++)
  339.     param[i] = 0;
  340.   while (match(")") == 0) {
  341.     if (number(¶m[n % count]) == INT) {
  342.       blanks();
  343.       match(",");
  344.       }
  345.     else {
  346.       error("illegal task parameter");
  347.       skip();
  348.       }
  349.     n++;
  350.     if(endst()) break;
  351.     }
  352.  
  353.   return n;
  354. }
  355.  
  356. /*
  357. ** begin a function
  358. **
  359. ** called from "parse" and tries to make a function
  360. ** out of the following text
  361. */
  362. dofunction()  {
  363.   int mon,             /* monitor keyword encountered flag */
  364.   task,             /* task keyword encountered flag */
  365.   intr,             /* interrupt keyword encountered flag */
  366.   param[2];            /* task/interrupt function parameters */
  367.   char fnname[NAMESIZE];    /* name of function being processed */
  368.   char *ptr;
  369.   nogo   =                      /* enable goto statements */
  370.   noloc  =                      /* enable block-local declarations */
  371.   lastst =                      /* no statement yet */
  372.   litptr = 0;                   /* clear lit pool */
  373.   litlab = getlabel();          /* label next lit pool */
  374.   locptr = STARTLOC;            /* clear local variables */
  375.   
  376.   entry = task = mon = intr = 0; /* reset keyword encountered flags */
  377.  
  378.   /* check keywords before function */
  379.   if(match("void")) blanks();    /* skip "void" & locate header */
  380.   if (match("entry")) {
  381.     /* monitor entry */
  382.     entry = 1;
  383.     blanks();
  384.     }
  385.   else if (match("monitor")) {
  386.     /* monitor initialization */
  387.     if (moninit)
  388.     {
  389.         error("Multiple monitor initialization definition");
  390.         errflag = 0;
  391.         kill();                     /* invalidate line */
  392.         return;
  393.     }
  394.     moninit = mon = 1;
  395.     blanks();
  396.     }
  397.   else if (match("task")) {
  398.     /* task definitation */
  399.     task = 1;
  400.     blanks();
  401.     }
  402.   else if (match("interrupt")) {
  403.     /* interrupt function */
  404.     intr = 1;
  405.     blanks();
  406.     }
  407.   if(monitor) lout(line, stderr);
  408.   if(symname(ssname) == 0) {
  409.     error("illegal function or declaration");
  410.     errflag = 0;
  411.     kill();                     /* invalidate line */
  412.     return;
  413.     }
  414.   strcpy(fnname, ssname);
  415.   if(ptr = findglb(ssname)) {   /* already in symbol table? */
  416.     if(ptr[CLASS] == AUTOEXT)
  417.          ptr[CLASS] = STATIC;
  418.     else multidef(ssname);
  419.     }
  420.   else
  421.     addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC);
  422.   public(FUNCTION);
  423.   argstk = 0;                  /* init arg count */
  424.   if(match("(") == 0) error("no open paren");
  425.   if (task) {
  426.     if (getparms(param, 2) > 2)
  427.       error("too many parameters");
  428.     }
  429.   else if (intr) {
  430.     int n;
  431.     n = getparms(param, 1);
  432.     if (n > 1)
  433.       error("too many parameters");
  434.     else if (n == 0)
  435.       error("missing interrupt number");
  436.     }
  437.   else {
  438.     while(match(")") == 0) {     /* then count args */
  439.       if(symname(ssname)) {
  440.         if(findloc(ssname)) multidef(ssname);
  441.         else {
  442.           addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC);
  443.           argstk += BPW;
  444.           }
  445.         }
  446.       else {
  447.         error("illegal argument name");
  448.         skip();
  449.         }
  450.       blanks();
  451.       if(streq(lptr,")") == 0 && match(",") == 0)
  452.         error("no comma");
  453.       if(endst()) break;
  454.       }
  455.     }
  456.   csp = 0;                     /* preset stack ptr */
  457.   argtop = argstk+BPW;         /* account for the pushed BP */
  458.   if (argstk && mon) 
  459.     error("No arguments allowed for monitor initialization");
  460.   while(argstk) {
  461.     if     (amatch("char",     4)) {doargs(CHR);  ns();}
  462.     else if(amatch("int",      3)) {doargs(INT);  ns();}
  463.     else if(amatch("unsigned", 8)) {
  464.       if   (amatch("char", 4))     {doargs(UCHR); ns();}
  465.       else {amatch("int", 3);       doargs(UINT); ns();}
  466.       }
  467.     else {error("wrong number of arguments"); break;}
  468.     }
  469.   gen(ENTER, 0);
  470.   if (strcmp(ssname, "main") == 0)
  471.     /* generate Concurrent Small C initialization P-code */
  472.     gen(CSCINIT, 0);
  473.   else if (entry)
  474.     /* generate Enter Monitor P-code */
  475.     gen(ENTERM, 0);
  476.   statement();
  477.   if(lastst != STRETURN && lastst != STGOTO)
  478.     {
  479.     /* generate Exit Monitor P-code */
  480.     if (entry) gen(EXITM, 0);
  481.     gen(RETURN, 0);
  482.     }
  483.   if(litptr) {
  484.     toseg(DATASEG);
  485.     gen(REFm, litlab);
  486.     dumplits(1);               /* dump literals */
  487.     }
  488.  
  489.   /* output monitor initialization table */
  490.   if (mon) {
  491.     sprintf(tmpbuf, "MNTRS(_%s)", fnname);
  492.     outline(tmpbuf);
  493.     }
  494.   else if (task) {
  495.     sprintf(tmpbuf, "TASKS(_%s, %d, %d)", fnname, param[0], param[1]);
  496.     outline(tmpbuf);
  497.     }
  498.   else if (intr) {
  499.     sprintf(tmpbuf, "INTRS(_%s, %d)", fnname, param[0]);
  500.     outline(tmpbuf);
  501.     }
  502.   }
  503.  
  504. /*
  505. ** declare argument types
  506. */
  507. doargs(type) int type; {
  508.   int id, sz;
  509.   char c, *ptr;
  510.   while(1) {
  511.     if(argstk == 0) return;           /* no arguments */
  512.     if(decl(type, POINTER, &id, &sz)) {
  513.       if(ptr = findloc(ssname)) {
  514.         ptr[IDENT] = id;
  515.         ptr[TYPE]  = type;
  516.         putint(sz, ptr+SIZE, 2);
  517.         putint(argtop-getint(ptr+OFFSET, 2), ptr+OFFSET, 2);
  518.         }
  519.       else error("not an argument");
  520.       }
  521.     argstk = argstk - BPW;            /* cnt down */
  522.     if(endst()) return;
  523.     if(match(",") == 0) error("no comma");
  524.     }
  525.   }
  526.  
  527. /*
  528. ** parse next local or argument declaration
  529. */
  530. decl(type, aid, id, sz) int type, aid, *id, *sz; {
  531.   int n, p;
  532.   if(match("(")) p = 1;
  533.   else           p = 0;
  534.   if(match("*"))        {*id = POINTER;  *sz  = BPW;}
  535.   else                  {*id = VARIABLE; *sz  = type >> 2;}
  536.   if((n = symname(ssname)) == 0) illname();
  537.   if(p && match(")")) ;
  538.   if(match("(")) {
  539.     if(!p || *id != POINTER) error("try (*...)()");
  540.     need(")");
  541.     }
  542.   else if(*id == VARIABLE && match("[")) {
  543.     *id = aid;
  544.     if((*sz *= needsub()) == 0) {
  545.       if(aid == ARRAY) error("need array size");
  546.       *sz  = BPW;      /* size of pointer argument */
  547.       }
  548.     }
  549.   return n;
  550.   }
  551.  
  552. /******************** start 2nd level parsing *******************/
  553.  
  554. /*
  555. ** statement parser
  556. */
  557. statement() {
  558.   if(ch == 0 && eof) return;
  559.   else if(amatch("char",     4)) {declloc(CHR);    ns();}
  560.   else if(amatch("int",      3)) {declloc(INT);    ns();}
  561.   else if(amatch("unsigned", 8)) {
  562.     if   (amatch("char",     4)) {declloc(UCHR);   ns();}
  563.     else {amatch("int",      3);  declloc(UINT);   ns();}
  564.     }
  565.   else {
  566.     if(declared >= 0) {
  567.       if(ncmp > 1) nogo = declared;   /* disable goto */
  568.       gen(ADDSP, csp - declared);
  569.       declared = -1;
  570.       }
  571.     if(match("{"))                 compound();
  572.     else if(amatch("if",       2)) {doif();           lastst = STIF;}
  573.     else if(amatch("while",    5)) {dowhile();        lastst = STWHILE;}
  574.     else if(amatch("do",       2)) {dodo();           lastst = STDO;}
  575.     else if(amatch("for",      3)) {dofor();          lastst = STFOR;}
  576.     else if(amatch("switch",   6)) {doswitch();       lastst = STSWITCH;}
  577.     else if(amatch("case",     4)) {docase();         lastst = STCASE;}
  578.     else if(amatch("default",  7)) {dodefault();      lastst = STDEF;}
  579.     else if(amatch("goto",     4)) {dogoto();         lastst = STGOTO;}
  580.     else if(dolabel())                                lastst = STLABEL;
  581.     else if(amatch("return",   6)) {doreturn(); ns(); lastst = STRETURN;}
  582.     else if(amatch("break",    5)) {dobreak();  ns(); lastst = STBREAK;}
  583.     else if(amatch("continue", 8)) {docont();   ns(); lastst = STCONT;}
  584.     else if(match(";"))            errflag = 0;
  585.     else if(match("#asm"))         {doasm();          lastst = STASM;}
  586.     else                           {doexpr(NO); ns(); lastst = STEXPR;}
  587.     }
  588.   return lastst;
  589.   }
  590.  
  591. /*
  592. ** declare local variables
  593. */
  594. declloc(type)  int type;  {
  595.   int id, sz;
  596.   if(swactive)     error("not allowed in switch");
  597.   if(noloc)        error("not allowed with goto");
  598.   if(declared < 0) error("must declare first in block");
  599.   while(1) {
  600.     if(endst()) return;
  601.     decl(type, ARRAY, &id, &sz);
  602.     declared += sz;
  603.     addsym(ssname, id, type,  sz, csp - declared, &locptr, AUTOMATIC);
  604.     if(match(",") == 0) return;
  605.     }
  606.   }
  607.  
  608. compound()  {
  609.   int savcsp;
  610.   char *savloc;
  611.   savcsp = csp;
  612.   savloc = locptr;
  613.   declared = 0;           /* may now declare local variables */
  614.   ++ncmp;                 /* new level open */
  615.   while (match("}") == 0)
  616.     if(eof) {
  617.       error("no final }");
  618.       break;
  619.       }
  620.     else statement();     /* do one */
  621.   if(--ncmp               /* close current level */
  622.   && lastst != STRETURN
  623.   && lastst != STGOTO)
  624.     gen(ADDSP, savcsp);   /* delete local variable space */
  625.   cptr = savloc;          /* retain labels */
  626.   while(cptr < locptr) {
  627.     cptr2 = nextsym(cptr);
  628.     if(cptr[IDENT] == LABEL) {
  629.       while(cptr < cptr2) *savloc++ = *cptr++;
  630.       }
  631.     else cptr = cptr2;
  632.     }
  633.   locptr = savloc;        /* delete local symbols */
  634.   declared = -1;          /* may not declare variables */
  635.   }
  636.  
  637. doif()  {
  638.   int flab1, flab2;
  639.   test(flab1 = getlabel(), YES);  /* get expr, and branch false */
  640.   statement();                    /* if true, do a statement */
  641.   if(amatch("else", 4) == 0) {    /* if...else ? */
  642.     /* simple "if"...print false label */
  643.     gen(LABm, flab1);
  644.     return;                       /* and exit */
  645.     }
  646.   flab2 = getlabel();
  647.   if(lastst != STRETURN && lastst != STGOTO)
  648.     gen(JMPm, flab2);
  649.   gen(LABm, flab1);    /* print false label */
  650.   statement();         /* and do "else" clause */
  651.   gen(LABm, flab2);    /* print true label */
  652.   }
  653.  
  654. dowhile()  {
  655.   int wq[4];              /* allocate local queue */
  656.   addwhile(wq);           /* add entry to queue for "break" */
  657.   gen(LABm, wq[WQLOOP]);  /* loop label */
  658.   test(wq[WQEXIT], YES);  /* see if true */
  659.   statement();            /* if so, do a statement */
  660.   gen(JMPm, wq[WQLOOP]);  /* loop to label */
  661.   gen(LABm, wq[WQEXIT]);  /* exit label */
  662.   delwhile();             /* delete queue entry */
  663.   }
  664.  
  665. dodo() {
  666.   int wq[4];
  667.   addwhile(wq);
  668.   gen(LABm, wq[WQLOOP]);
  669.   statement();
  670.   need("while");
  671.   test(wq[WQEXIT], YES);
  672.   gen(JMPm, wq[WQLOOP]);
  673.   gen(LABm, wq[WQEXIT]);
  674.   delwhile();
  675.   ns();
  676.   }
  677.  
  678. dofor() {
  679.   int wq[4], lab1, lab2;
  680.   addwhile(wq);
  681.   lab1 = getlabel();
  682.   lab2 = getlabel();
  683.   need("(");
  684.   if(match(";") == 0) {
  685.     doexpr(NO);           /* expr 1 */
  686.     ns();
  687.     }
  688.   gen(LABm, lab1);
  689.   if(match(";") == 0) {
  690.     test(wq[WQEXIT], NO); /* expr 2 */
  691.     ns();
  692.     }
  693.   gen(JMPm, lab2);
  694.   gen(LABm, wq[WQLOOP]);
  695.   if(match(")") == 0) {
  696.     doexpr(NO);           /* expr 3 */
  697.     need(")");
  698.     }
  699.   gen(JMPm, lab1);
  700.   gen(LABm, lab2);
  701.   statement();
  702.   gen(JMPm, wq[WQLOOP]);
  703.   gen(LABm, wq[WQEXIT]);
  704.   delwhile();
  705.   }
  706.  
  707. doswitch() {
  708.   int wq[4], endlab, swact, swdef, *swnex, *swptr;
  709.   swact = swactive;
  710.   swdef = swdefault;
  711.   swnex = swptr = swnext;
  712.   addwhile(wq);
  713.   *(wqptr + WQLOOP - WQSIZ) = 0;
  714.   need("(");
  715.   doexpr(YES);                /* evaluate switch expression */
  716.   need(")");
  717.   swdefault = 0;
  718.   swactive = 1;
  719.   gen(JMPm, endlab = getlabel());
  720.   statement();                /* cases, etc. */
  721.   gen(JMPm, wq[WQEXIT]);
  722.   gen(LABm, endlab);
  723.   gen(SWITCH, 0);             /* match cases */
  724.   while(swptr < swnext) {
  725.     gen(NEARm, *swptr++);
  726.     gen(WORDn,  *swptr++);    /* case value */
  727.     }
  728.   gen(WORDn, 0);
  729.   if(swdefault) gen(JMPm, swdefault);
  730.   gen(LABm, wq[WQEXIT]);
  731.   delwhile();
  732.   swnext    = swnex;
  733.   swdefault = swdef;
  734.   swactive  = swact;
  735.   }
  736.  
  737. docase() {
  738.   if(swactive == 0) error("not in switch");
  739.   if(swnext > swend) {
  740.     error("too many cases");
  741.     return;
  742.     }
  743.   gen(LABm, *swnext++ = getlabel());
  744.   constexpr(swnext++);
  745.   need(":");
  746.   }
  747.  
  748. dodefault() {
  749.   if(swactive) {
  750.     if(swdefault) error("multiple defaults");
  751.     }
  752.   else error("not in switch");
  753.   need(":");
  754.   gen(LABm, swdefault = getlabel());
  755.   }
  756.  
  757. dogoto() {
  758.   if(nogo > 0) error("not allowed with block-locals");
  759.   else noloc = 1;
  760.   if(symname(ssname)) gen(JMPm, addlabel(NO));
  761.   else error("bad label");
  762.   ns();
  763.   }
  764.  
  765. dolabel() {
  766.   char *savelptr;
  767.   blanks();
  768.   savelptr = lptr;
  769.   if(symname(ssname)) {
  770.     if(gch() == ':') {
  771.       gen(LABm, addlabel(YES));
  772.       return 1;
  773.       }
  774.     else bump(savelptr-lptr);
  775.     }
  776.   return 0;
  777.   }
  778.  
  779. addlabel(def) int def; {
  780.   if(cptr = findloc(ssname)) {
  781.     if(cptr[IDENT] != LABEL) error("not a label");
  782.     else if(def) {
  783.       if(cptr[TYPE]) error("duplicate label");
  784.       else cptr[TYPE] = YES;
  785.       }
  786.     }
  787.   else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL);
  788.   return (getint(cptr+OFFSET, 2));
  789.   }
  790.  
  791. doreturn()  {
  792.   int savcsp;
  793.   if(endst() == 0) doexpr(YES);
  794.   savcsp = csp;
  795.   /* generate EXIT MONITOR P-code */
  796.   if (entry) gen(EXITM, 0);
  797.   gen(RETURN, 0);
  798.   csp = savcsp;
  799.   }
  800.  
  801. dobreak()  {
  802.   int *ptr;
  803.   if((ptr = readwhile(wqptr)) == 0) return;
  804.   gen(ADDSP, ptr[WQSP]);
  805.   gen(JMPm, ptr[WQEXIT]);
  806.   }
  807.  
  808. docont()  {
  809.   int *ptr;
  810.   ptr = wqptr;
  811.   while (1) {
  812.     if((ptr = readwhile(ptr)) == 0) return;
  813.     if(ptr[WQLOOP]) break;
  814.     }
  815.   gen(ADDSP, ptr[WQSP]);
  816.   gen(JMPm, ptr[WQLOOP]);
  817.   }
  818.  
  819. doasm()  {
  820.   ccode = 0;           /* mark mode as "asm" */
  821.   while (1) {
  822.     inline();
  823.     if(match("#endasm")) break;
  824.     if(eof)break;
  825.     fputs(line, output);
  826.     }
  827.   kill();
  828.   ccode = 1;
  829.   }
  830.  
  831. doexpr(use) int use; {
  832.   int const, val;
  833.   int *before, *start;
  834.   usexpr = use;        /* tell isfree() whether expr value is used */
  835.   while(1) {
  836.     setstage(&before, &start);
  837.     expression(&const, &val);
  838.     clearstage(before, start);
  839.     if(ch != ',') break;
  840.     bump(1);
  841.     }
  842.   usexpr = YES;        /* return to normal value */
  843.   }
  844.  
  845. /******************** miscellaneous functions *******************/
  846.  
  847. /*
  848. ** get run options
  849. */
  850. ask() {
  851.   int i;
  852.   i = listfp = nxtlab = 0;
  853.   output = stdout;
  854.   optimize = YES;
  855.   alarm = monitor = pause = NO;
  856.   line = mline;
  857.   while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF) {
  858.     if(line[0] != '-' && line[0] != '/') continue;
  859.     if(toupper(line[1]) == 'L'
  860.     && isdigit(line[2])
  861.     && line[3] <= ' ') {
  862.       listfp = line[2]-'0';
  863.       continue;
  864.       }
  865.     if(toupper(line[1]) == 'N'
  866.     && toupper(line[2]) == 'O'
  867.     && line[3] <= ' ') {
  868.       optimize = NO;
  869.       continue;
  870.       }
  871.     if(line[2] <= ' ') {
  872.       if(toupper(line[1]) == 'A') {alarm   = YES; continue;}
  873.       if(toupper(line[1]) == 'M') {monitor = YES; continue;}
  874.       if(toupper(line[1]) == 'P') {pause   = YES; continue;}
  875.       }
  876.     fputs("usage: csc [file]... [-m] [-a] [-p] [-l#] [-no]\n", stderr);
  877.     abort(ERRCODE);
  878.     }
  879.   }
  880.  
  881. /*
  882. ** input and output file opens
  883. */
  884. openfile() {        /* entire function revised */
  885.   char outfn[15];
  886.   int i, j, ext;
  887.   input = EOF;
  888.   while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) {
  889.     if(pline[0] == '-' || pline[0] == '/') continue;
  890.     ext = NO;
  891.     i = -1;
  892.     j = 0;
  893.     while(pline[++i]) {
  894.       if(pline[i] == '.') {
  895.         ext = YES;
  896.         break;
  897.         }
  898.       if(j < 10) outfn[j++] = pline[i];
  899.       }
  900.     if(!ext) strcpy(pline + i, ".C");
  901.     input = mustopen(pline, "r");
  902.     if(!files && iscons(stdout)) {
  903.       strcpy(outfn + j, ".M4");
  904.       output = mustopen(outfn, "w");
  905.       }
  906.     outfn[j] = 0;
  907.     sprintf(tmpbuf, "MODULENAME(%s)", outfn);
  908.     outline(tmpbuf);
  909.     files = YES;
  910.     kill();
  911.     return;
  912.     }
  913.   if(files++) eof = YES;
  914.   else input = stdin;
  915.   kill();
  916.   }
  917.  
  918. /*
  919. ** open a file with error checking
  920. */
  921. mustopen(fn, mode) char *fn, *mode; {
  922.   int fd;
  923.   if(fd = fopen(fn, mode)) return fd;
  924.   fputs("open error on ", stderr);
  925.   lout(fn, stderr);
  926.   abort(ERRCODE);
  927.   }
  928.  
  929.